from apps.goods.models import *
from rest_framework import serializers
from django.db import transaction


class SKUSpecSerializer(serializers.ModelSerializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        model = SKUSpecification
        fields = ("spec_id", "option_id")


class SKUSerializer(serializers.ModelSerializer):
    # 被关联的字段 序化输入
    specs = SKUSpecSerializer(many=True)
    # 外键字段 用来做序化输出 StringRelatedField
    spu = serializers.StringRelatedField(read_only=True)
    category = serializers.StringRelatedField(read_only=True)
    # 外键字段 用来做反序化写入
    spu_id = serializers.IntegerField()
    category_id = serializers.IntegerField()

    class Meta:
        model = SKU
        fields = "__all__"

    # 反序化 保存数据到数据库 操作两个表格
    def create(self, validated_data):
        # 反序化写入数据的时候 sku表中没有 specs 字段 需要进行判断
        if validated_data["specs"]:
            specs = validated_data["specs"]
            del validated_data["specs"]
        # 连表操作 开启实务
        with transaction.atomic():
            # 这是回滚点
            savepoint = transaction.savepoint()
            try:
                sku = SKU.objects.create(**validated_data)
                # 遍历 规格数据 分别写入规格表
                for spec in specs:
                    spec_id = spec.get("spec_id")
                    option_id = spec.get("option_id")
                    SKUSpecification.objects.create(sku=sku, spec_id=spec_id, option_id=option_id)
            except Exception as e:
                # 异常出错 回滚
                transaction.savepoint_rollback(savepoint)
                raise serializers.ValidationError("数据库出错")
            # 正常结束 提交实务
            transaction.savepoint_commit(savepoint)
            # 页面静态化 需要传入 default_image 字段 否则 异步任务会报错
            sku.default_image = "group1/M00/00/02/CtM3BVrRbh2AX3JVAAFvJD02RWs4638828"
            sku.save()
            from celery_tasks.html.tasks import generate_static_sku_detail_html
            generate_static_sku_detail_html.delay(sku.id)
            return sku

    # 更新操作 同样需要操作两个表格
    def update(self, instance, validated_data):
        # 同样判断数据中是否存在 specs
        if validated_data["specs"]:
            specs = validated_data["specs"]
            del validated_data["specs"]
        # 连表操作 开启实务
        # 根据实例对象更新sku表格数据
        with transaction.atomic():
            # 设置回滚点
            savepoint = transaction.savepoint()
            try:
                # 开始更新 sku表
                SKU.objects.filter(id=instance.id).update(**validated_data)
                # 同时更新 spec表格
                # 先删除对应sku规格信息然后再更新
                SKUSpecification.objects.filter(sku_id=instance.id).delete()
                for spec in specs:
                    spec_id = spec.get("spec_id")
                    option_id = spec.get("option_id")
                    SKUSpecification.objects.create(sku_id=instance.id, spec_id=spec_id, option_id=option_id)
            except Exception as e:
                # 异常回滚
                transaction.savepoint_rollback(savepoint)
                raise serializers.ValidationError('数据库错误')
            # 正常 提交实务
            transaction.savepoint_commit(savepoint)
            return instance


class GoodsCategorySerializer(serializers.ModelSerializer):

    class Meta:
        model = GoodsCategory
        fields = "__all__"


class SPUSimpleSerializer(serializers.ModelSerializer):

    class Meta:
        model = SPU
        fields = '__all__'


class SpecOptionSerializer(serializers.ModelSerializer):

    class Meta:
        model = SpecificationOption
        fields = ('id', 'value')


class SPUSpecsViewSerializer(serializers.ModelSerializer):
    # 反查规格选项表 related_name = options 只做序化输出 一对多 设置 many 参数
    options = SpecOptionSerializer(read_only=True, many=True)

    class Meta:
        model = SPUSpecification
        fields = "__all__"
